package com.yifeng.service.impl;

import com.yifeng.common.Constants;
import com.yifeng.common.Result;
import com.yifeng.dao.ResourceDao;
import com.yifeng.factory.DAOFactory;
import com.yifeng.model.FileInfo;
import com.yifeng.model.Resource;
import com.yifeng.model.User;
import com.yifeng.service.FileStorageService;
import com.yifeng.service.ResourceService;
import com.yifeng.util.AliOssUtil;
import com.yifeng.util.FileUtil;
import org.apache.commons.io.IOUtils;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.List;

public class ResourceServiceImpl implements ResourceService {

    private final ResourceDao resourceDao = DAOFactory.getResourceDao();
    private final FileStorageService fileStorageService = new FileStorageServiceImpl();

    @Override
    public Result uploadResource(Part filePart, String uploader) {


        try {
            // 参数验证
            if (filePart == null || filePart.getSize() == 0) {

                return Result.fail(400,"未上传文件");
            }

            // 保存文件到磁盘
            FileInfo fileInfo = fileStorageService.saveFile(filePart);

          // 判断资源类型（必须与数据库 ENUM 值完全一致！）
            String resourceType;
            if (fileInfo.isImage()) {
                resourceType = Constants.RESOURCE_TYPE_IMAGE;   // "图片"
            } else if (fileInfo.isDocument()) {
                resourceType = Constants.RESOURCE_TYPE_DOCUMENT; // "文档"
            } else if (fileInfo.isVideo()) {
                resourceType = Constants.RESOURCE_TYPE_VIDEO;    // "视频"
            } else {
                // 可选：拒绝非支持类型，或归为“其他”（但数据库 ENUM 必须包含“其他”）
                return Result.fail(403,"不支持的文件类型，请上传图片、文档或视频");
            }

            //存储到oss云服务器中
            String uploadPath = AliOssUtil.upload(filePart);


            // 创建资源对象
            Resource resource = new Resource();
            resource.setFileName(fileInfo.getOriginalFileName());
            resource.setUploader(uploader);
            resource.setType(resourceType);
            resource.setFilePath(uploadPath);
            resource.setFileSize(fileInfo.getFileSize());
            resource.setUploadTime(LocalDateTime.now());
            resource.setDownloadCount(0);


            //保存到数据库
            Result result = addResource(resource);

            return result;

        } catch (Exception e) {
            // 记录日志

            return Result.fail(406,"文件上传失败: " + e.getMessage());
        }
    }


    @Override
    public Result getAllResources() {

        try {

            List<Resource> resources = resourceDao.findResourceList();


            return Result.success(resources);
        } catch (Exception e) {

            return Result.fail(406,"查询资源失败");
        }
    }

    @Override
    public Result searchResources(String keyword) {

        try {
            if (keyword == null || keyword.trim().isEmpty()) {
                return Result.fail(406,"搜索关键词不能为空");
            }


            List<Resource> resources = resourceDao.searchByKeyword(keyword);


            return Result.success(resources);
        } catch (Exception e) {

            return Result.fail(406,"搜索失败");
        }
    }

    @Override
    public Result addResource(Resource resource) {


        //防御性编程（防止非法值）

        // 在 addResource 方法中
        if (   !Constants.RESOURCE_TYPE_DOCUMENT.equals(resource.getType()) &&
                !Constants.RESOURCE_TYPE_IMAGE.equals(resource.getType()) &&
                !Constants.RESOURCE_TYPE_VIDEO.equals(resource.getType())) {
            return Result.fail(403,"无效的资源类型");
        }


        try {
            if (resource == null) {
                return Result.fail(406,"资源对象不能为空");
            }
            if (resource.getFileName() == null || resource.getFileName().trim().isEmpty()) {
                return Result.fail(406,"资源名称不能为空");
            }
            if (resource.getUploader() == null || resource.getUploader().trim().isEmpty()) {
                return Result.fail(406,"上传者不能为空");
            }
            if (resource.getType() == null || resource.getType().trim().isEmpty()) {
                return Result.fail(406,"资源类型不能为空");
            }
            if (resource.getFilePath() == null || resource.getFilePath().trim().isEmpty()) {
                return Result.fail(406,"文件路径不能为空");
            }
            if (resource.getFileSize() == null || resource.getFileSize() <= 0) {
                return Result.fail(406,"文件大小必须大于0");
            }

            boolean success = resourceDao.insert(resource);
            if (success) {

                return Result.success();

            } else {

                return Result.fail(406,"资源上传失败，请重试");
            }
        } catch (Exception e) {

            return Result.fail(406,"添加资源失败");
        }
    }

    @Override
    public Result deleteResourceById(Integer resourceId) {
        try {
            if (resourceId == null || resourceId <= 0) {
                return Result.fail(400,"资源ID无效");
            }

            // 先查询资源信息（获取文件路径）
            Resource resource = resourceDao.findResourceById(resourceId);
            if (resource == null) {
                return Result.fail(406,"资源不存在");
            }

            // 删除数据库记录
            boolean dbDeleted = resourceDao.delete(resourceId);
            if (!dbDeleted) {
                return Result.fail(406,"数据库删除失败");
            }

            // 删除服务器上的物理文件
           /* String filePath = resource.getFilePath(); // 这是相对路径，如 "uploads/xxx.jpg"
            boolean fileDeleted = fileStorageService.deleteFile(filePath);

            if (!fileDeleted) {
              // 可选：记录警告日志，但不要回滚数据库（因为文件可能已被手动删除）
              System.err.println("警告：物理文件未找到或删除失败: " + filePath);
            }
*/
            return Result.success();

        } catch (Exception e) {
            e.printStackTrace();
            return Result.fail(406,"删除资源失败: " + e.getMessage());
        }
    }

    @Override
    public Result downloadResource(int resourceId, HttpServletResponse resp) {
        try {
            // 1. 查询资源信息
            Resource resource = resourceDao.findResourceById(resourceId);
            if (resource == null) {
                return Result.fail(406,"资源不存在");
            }


            String filePath = resource.getFilePath(); // 这是 OSS URL也可能是相对路径，如 "uploads/xxx.pdf"

            // 如果 filePath 是一个有效的 URL（比如包含 http），直接重定向
            if (filePath != null && (filePath.startsWith("http://") || filePath.startsWith("https://"))) {
                // 可选：更新下载次数
                resourceDao.incrementDownloadCount(resourceId);

                // 重定向到 OSS 地址（浏览器会自动下载）
                resp.sendRedirect(filePath);
                return null; // 已完成响应
            }
            // 2. 获取文件对象
            File file = fileStorageService.getFile(filePath);
            if (file == null || !file.exists()) {
                return Result.fail(406,"文件不存在或已被删除");
            }

            // 3. 设置响应头
            resp.setContentType("application/octet-stream");
            resp.setHeader("Content-Disposition", "attachment; filename=\"" +
            URLEncoder.encode(resource.getFileName(), "UTF-8") + "\"");
            resp.setHeader("Content-Length", String.valueOf(file.length()));
            resp.setHeader("Cache-Control", "no-cache");

            // 4. 写入文件流
            try  {
                //创建输入流
                FileInputStream fis = new FileInputStream(file);
                //获取输出流，用于将文件写入http响应
                OutputStream os = resp.getOutputStream();
                //使用上传依赖将输入流内容复制到输出流，实现文件传输
                IOUtils.copy(fis,os);
                //关闭输入流，释放资源
                IOUtils.closeQuietly(fis);
                //关闭输出流
                IOUtils.closeQuietly(os);
                // 5. 更新下载次数（可选）
                resourceDao.incrementDownloadCount(resourceId);
            } catch (Exception e) {
                // 下载成功但计数失败，可记录日志但不中断下载
                System.err.println("警告：下载次数更新失败，resourceId=" + resourceId);
            }

            return null; // 注意：此时响应已写入，不应再返回 JSON
        } catch (Exception e) {
            e.printStackTrace();
            return Result.fail(406,"文件下载失败: " + e.getMessage());
        }
    }


}